﻿using System;
using System.Configuration;
using System.Messaging;
using System.ServiceModel;
using System.ServiceModel.Description;
using VideoStore.Services;
using VideoStore.Services.Interface;

namespace TestDriver.VideoStore.Host
{
    class Program
    {
        private const string MSG = "{0} Service started!";

        static void Main(string[] args)
        {
            CreateQueue();

            Console.WriteLine("Starting VideoStore services...");
            Console.WriteLine();
            try
            {
                var customerHost = new ServiceHost(typeof(CustomerService));
                var smbCustomer = new ServiceMetadataBehavior();
                customerHost.Description.Behaviors.Add(smbCustomer);
                customerHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "net.tcp://localhost:8000/CustomerService/mex/");
                var customerBinding = new NetTcpBinding();
                customerBinding.TransactionFlow = true;
                customerBinding.TransactionProtocol = TransactionProtocol.OleTransactions;
                customerHost.AddServiceEndpoint(typeof(ICustomerService), customerBinding, "net.tcp://localhost:8000/CustomerService");
                customerHost.Open();
                Console.WriteLine(MSG, "Customer");

                var catalogueHost = new ServiceHost(typeof(CatalogueService));
                var smbCatalogue = new ServiceMetadataBehavior();
                catalogueHost.Description.Behaviors.Add(smbCatalogue);
                catalogueHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "net.tcp://localhost:8000/CatalogueService/mex/");
                var catalogueBinding = new NetTcpBinding();
                catalogueBinding.TransactionFlow = true;
                catalogueBinding.TransactionProtocol = TransactionProtocol.OleTransactions;
                catalogueHost.AddServiceEndpoint(typeof(ICatalogueService), catalogueBinding, "net.tcp://localhost:8000/CatalogueService");
                catalogueHost.Open();
                Console.WriteLine(MSG, "Catalogue");

                var orderHost = new ServiceHost(typeof(OrderService));
                var smbOrder = new ServiceMetadataBehavior();
                orderHost.Description.Behaviors.Add(smbOrder);
                orderHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "net.tcp://localhost:8000/OrderService/mex/");
                var orderBinding = new NetTcpBinding();
                orderBinding.TransactionFlow = true;
                orderBinding.TransactionProtocol = TransactionProtocol.OleTransactions;
                orderHost.AddServiceEndpoint(typeof(IOrderService), orderBinding, "net.tcp://localhost:8000/OrderService");
                orderHost.Open();
                Console.WriteLine(MSG, "Order");

                var orderQueuedHost = new ServiceHost(typeof(OrderServiceQueued));
                var smbOrderQueued = new ServiceMetadataBehavior();
                orderQueuedHost.Description.Behaviors.Add(smbOrderQueued);
                orderQueuedHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "net.tcp://localhost:8000/OrderServiceQueued/mex/");
                var orderQueuedBinding = new NetMsmqBinding();
                orderQueuedBinding.Security.Mode = NetMsmqSecurityMode.None;
                orderQueuedBinding.Durable = true;
                orderQueuedBinding.ExactlyOnce = true;
                orderQueuedHost.AddServiceEndpoint(typeof(IOrderServiceQueued), orderQueuedBinding, "net.msmq://localhost/private/VideoStore/StatusQueue");
                orderQueuedHost.Open();
                Console.WriteLine(MSG, "Order (Queued)");

                var stockHost = new ServiceHost(typeof(StockService));
                var smbStock = new ServiceMetadataBehavior();
                stockHost.Description.Behaviors.Add(smbStock);
                stockHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "net.tcp://localhost:8000/StockService/mex/");
                var stockBinding = new NetTcpBinding();
                stockBinding.TransactionFlow = true;
                stockBinding.TransactionProtocol = TransactionProtocol.OleTransactions;
                stockHost.AddServiceEndpoint(typeof(IStockService), stockBinding, "net.tcp://localhost:8000/StockService");
                stockHost.Open();
                Console.WriteLine(MSG, "Stock");

                var storeHost = new ServiceHost(typeof(StoreService));
                var smbStore = new ServiceMetadataBehavior();
                storeHost.Description.Behaviors.Add(smbStore);
                storeHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "net.tcp://localhost:8000/StoreService/mex/");
                var storeBinding = new NetTcpBinding();
                storeBinding.TransactionFlow = true;
                storeBinding.TransactionProtocol = TransactionProtocol.OleTransactions;
                storeHost.AddServiceEndpoint(typeof(IStoreService), storeBinding, "net.tcp://localhost:8000/StoreService");
                storeHost.Open();
                Console.WriteLine(MSG, "Store");

                var warehouseHost = new ServiceHost(typeof(WarehouseService));
                var smbWarehouse = new ServiceMetadataBehavior();
                warehouseHost.Description.Behaviors.Add(smbWarehouse);
                warehouseHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "net.tcp://localhost:8000/WarehouseService/mex/");
                var warehouseBinding = new NetTcpBinding();
                warehouseBinding.TransactionFlow = true;
                warehouseBinding.TransactionProtocol = TransactionProtocol.OleTransactions;
                warehouseHost.AddServiceEndpoint(typeof(IWarehouseService), warehouseBinding, "net.tcp://localhost:8000/WarehouseService");
                warehouseHost.Open();
                Console.WriteLine(MSG, "Warehouse");

                Console.WriteLine();
                Console.WriteLine("All Services started successfully!");
                Console.WriteLine();
                Console.WriteLine("Now listening to any Services update ... ");
                Console.WriteLine();
                Console.ReadKey();
            }
            catch (CommunicationException cmEx)
            {
                Console.WriteLine("Could not start services. Error: " + cmEx.Message);
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Could not start services. Error: " + ex.Message);
                Console.ReadKey();
            }
        }

        private static void CreateQueue()
        {
            string queueName = ConfigurationManager.AppSettings["queueName"];
            if (!MessageQueue.Exists(queueName))
            {
                MessageQueue.Create(queueName, true);
            }

            queueName = ConfigurationManager.AppSettings["statusQueueName"];
            if (!MessageQueue.Exists(queueName))
            {
                MessageQueue.Create(queueName, true);
            }
        }
    }
}